home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / cit.arc / ROOMB.C < prev   
Encoding:
C/C++ Source or Header  |  1986-01-11  |  23.8 KB  |  801 lines

  1. /************************************************************************/
  2. /*                roomb.c                 */
  3. /*        room code for Citadel bulletin board system        */
  4. /************************************************************************/
  5.  
  6. /************************************************************************/
  7. /*                History                 */
  8. /*                                    */
  9. /* 85Nov15 HAW    Create LIBROOM.C library file.                */
  10. /* 85Nov11 HAW    Rewrite Held message.                    */
  11. /* 85Nov06 HAW    MAXTEXT = 7500, add beep when near end of buffer.    */
  12. /* 85Nov03 HAW    Add good_path().                    */
  13. /* 85Aug24 HAW    Modify getString() for no return on '?' unless requested*/
  14. /* 85Aug17 HAW    Update to use onLine().                 */
  15. /* 85Jun27 HAW    Fix getText to ignore nulls.                */
  16. /* 85Jun22 HAW    Rewrite indexRooms() for speed.             */
  17. /* 85May16 HAW  Set up <H>old message feature.                          */
  18. /* 85Mar13 HAW    Move zapRoomFile() out of file.             */
  19. /* 85Mar03 HAW    Room replication bug fixed.                */
  20. /* 85Feb22 HAW    Implement upload/download stuff.            */
  21. /* 85Feb20 HAW    Implement IMPERVIOUS flag.                */
  22. /* 85Jan27 HAW    Fix replaceString().                    */
  23. /* 85Jan16 JLS    Fix getText so console starting CR creates blank msg.    */
  24. /* 85Jan16 HAW    Fix "Continue" extra space problem in editText.     */
  25. /* 85Jan14 HAW    Now editText prints recipient on <P>rint formatted.    */
  26. /* 85Jan15 HAW&JLS List rooms deleted by <.ad>.             */
  27. /* 85Jan14 HAW&JLS If room edited is private, now extra question.    */
  28. /* 84Oct15 HAW    Rooms were automagically becoming permanent.        */
  29. /* 84Sep17 HAW    indexRooms modified so it knows if it's CONFG or CTDL.    */
  30. /* 84Aug30 HAW    Into the 16-bit world we leap: MS-DOS!    <Gargle>    */
  31. /* 84Jun28 JLS    Enhancement: Creator of a room is listed in Aide>.    */
  32. /* 84Jun23 HAW & JLS  Local unused variables are zapped.        */
  33. /* 84Jun10 JLS    Room cannot have a name of length 0.            */
  34. /* 84May07 JLS & HAW Fix bug in makeRoom to ensure correct g. # inc.ed. */
  35. /* 84Apr04 HAW    Start upgrade to BDS 1.50a.                */
  36. /* 83Feb26 CrT    bug in makeRoom when out of rooms fixed.        */
  37. /* 83Feb26 CrT    matchString made caseless, normalizeString()        */
  38. /* 83Feb26 CrT    "]" directory prompt, user name before prompts        */
  39. /* 82Dec06 CrT    2.00 release.                        */
  40. /* 82Nov02 CrT    Cleanup prior to V1.2 mods.                */
  41. /* 82Nov01 CrT    Proofread for CUG distribution.             */
  42. /* 82Mar27 dvm    conversion to v. 1.4 begun                */
  43. /* 82Mar25 dvm    conversion for TRS-80/Omikron test started        */
  44. /* 81Dec21 CrT    Log file...                        */
  45. /* 81Dec20 CrT    Messages...                        */
  46. /* 81Dec19 CrT    Rooms seem to be working...                */
  47. /* 81Dec12 CrT    Started.                        */
  48. /************************************************************************/
  49.  
  50. #include "ctdl.h"
  51.  
  52. /************************************************************************/
  53. /*                Contents                */
  54. /*                                    */
  55. /*    editText()        handles the end-of-message-entry menu    */
  56. /*    findRoom()        find a free room            */
  57. /*    getNumber()        prompt user for a number, limited range */
  58. /*    getString()        read a string in from user        */
  59. /*    getText()        reads a message in from user        */
  60. /*    getYesNo()        prompts for a yes/no response        */
  61. /*    givePrompt()        gives usual "THISROOM>" prompt        */
  62. /*    # good_path()        gets subdirectory path from sysop    */
  63. /*    indexRooms()        build RAM index to ctdlroom.sys     */
  64. /*    makeRoom()        make new room via user dialogue     */
  65. /*    matchString()        search for given string         */
  66. /*    noteRoom()        enter room into RAM index        */
  67. /*    renameRoom()        sysop special to rename rooms        */
  68. /*    replaceString()     string-substitute for message entry    */
  69. /*    strTran()        transfer a string            */
  70. /*                                    */
  71. /*    # -- operating system dependent function.            */
  72. /************************************************************************/
  73.  
  74. /************************************************************************/
  75. /*            External variable declarations in ROOMB.C        */
  76. /************************************************************************/
  77.  
  78. /*******************************< none >*********************************/
  79.  
  80. /************************************************************************/
  81. /*            External variable definitions for ROOMB.C        */
  82. /************************************************************************/
  83. extern struct aRoom    roomBuf;    /* Room buffer            */
  84. extern struct rTable    roomTab[];    /* RAM index            */
  85. extern FILE        *roomfl;    /* Room file descriptor     */
  86. extern struct config    cfg;        /* Other variables        */
  87. extern struct msgB    msgBuf;     /* Message buffer        */
  88. extern struct        msgB tempMess;    /* For held messages        */
  89. extern struct logBuffer logBuf;     /* Person buffer        */
  90. extern int        thisRoom;    /* Current room         */
  91. extern char        outFlag;    /* Output flag            */
  92. extern char        loggedIn;    /* Logged in?            */
  93. extern char        haveCarrier;    /* Have carrier?        */
  94. extern char        onConsole;    /* How about on Console?    */
  95. extern char        whichIO;    /* Where is I/O?        */
  96. extern char        debug;        /* Debug flag            */
  97. extern char        expert;     /* expert?            */
  98. extern char        *baseRoom;
  99. extern char        heldMessage;
  100. extern int        exitValue;
  101. extern char        echo;
  102. extern char        echoChar;
  103.  
  104. /************************************************************************/
  105. /*            External function definitions for ROOMB.C        */
  106. /************************************************************************/
  107. char iChar();
  108. char getYesNo();
  109. char toUpper();
  110. int  fread();
  111.  
  112. /************************************************************************/
  113. /*    editText() handles the end-of-message-entry menu.        */
  114. /*    return TRUE  to save message to disk,                */
  115. /*           FALSE to abort message, and                */
  116. /*           ERROR if user decides to continue            */
  117. /************************************************************************/
  118. int editText(buf, lim)
  119. char *buf;
  120. int lim;
  121. {
  122.     do {
  123.     outFlag = IMPERVIOUS;
  124.     mPrintf("\n entry cmd: ");
  125.     switch (toUpper(iChar())) {
  126.     case 'A':
  127.         mPrintf("bort\n ");
  128.         if (getYesNo(" confirm")) {
  129.         msgBuf.mbto[0]     = 0;
  130.         msgBuf.mbaddr[0] = 0;
  131.         return FALSE;
  132.         }
  133.         break;
  134.     case 'C':
  135.         mPrintf("ontinue");
  136.         doCR();
  137.         return ERROR;
  138.     case 'P':
  139.         mPrintf("rint formatted\n ");
  140.         doCR();
  141.         outFlag = OUTOK;
  142.         mPrintf(   "   ");
  143.         printDate();
  144.         if (loggedIn)
  145.                 mPrintf(" from %s", msgBuf.mbauth);
  146.         if (thisRoom == MAILROOM)
  147.                 mPrintf(" to %s", msgBuf.mbto);
  148.         if (msgBuf.mbaddr[0])
  149.                 mPrintf(" (on %s)", msgBuf.mbaddr);
  150.         doCR();
  151.         mFormat(buf);
  152.         break;
  153.     case 'R':
  154.         mPrintf("eplace string\n ");
  155.         replaceString(buf, lim);
  156.         break;
  157.     case 'S':
  158.         mPrintf("ave buffer\n ");
  159.         return TRUE;
  160.         case 'H':
  161.             mPrintf("old message for later\n ");
  162.             if (heldMessage) {
  163.                 mPrintf("Message already being held!\n ");
  164.                 break;
  165.             }
  166.             mPrintf("Message held\n ");
  167.         strTran(tempMess.mbtext, msgBuf.mbtext);
  168.         if (msgBuf.mbto[0] != 0)
  169.         strTran(tempMess.mbto, msgBuf.mbto);
  170.         if (msgBuf.mbaddr[0] != 0)
  171.         strTran(tempMess.mbaddr, msgBuf.mbaddr);
  172.             heldMessage = TRUE;
  173.             return HELD;
  174.     case '?':
  175.         tutorial("edit.mnu");
  176.         break;
  177.     default:
  178.         if (!expert) tutorial("edit.mnu");
  179.         else mPrintf(" ? (Type '?' for menu)\n \n");
  180.         break;
  181.     }
  182.     } while (onLine());
  183.     return FALSE;
  184. }
  185.  
  186. /************************************************************************/
  187. /*    findRoom() returns # of free room if possible, else ERROR    */
  188. /************************************************************************/
  189. int findRoom()
  190. {
  191.     int roomRover;
  192.  
  193.     for (roomRover = 0;  roomRover < MAXROOMS;    roomRover++) {
  194.     if (roomTab[roomRover].rtflags.INUSE == 0) return roomRover;
  195.     }
  196.     return ERROR;
  197. }
  198.  
  199. /************************************************************************/
  200. /*    getNumber() prompts for a number in (bottom, top) range.    */
  201. /************************************************************************/
  202. int getNumber(prompt, bottom, top)
  203. char   *prompt;
  204. unsigned bottom;
  205. unsigned top;
  206. {
  207.     unsigned try;
  208.     char numstring[NAMESIZE];
  209.  
  210.     do {
  211.     getString(prompt, numstring, NAMESIZE, FALSE, ECHO);
  212.     try    = atoi(numstring);
  213.     if (try < bottom)  mPrintf("Sorry, must be at least %d\n", bottom);
  214.     if (try > top    )  mPrintf("Sorry, must be no more than %d\n", top);
  215.     } while ((try < bottom ||  try > top) && onLine());
  216.     return  try;
  217. }
  218.  
  219. /************************************************************************/
  220. /*    getString() gets a string from the user.            */
  221. /************************************************************************/
  222. getString(prompt, buf, lim, QuestIsSpecial, doEcho)
  223. char *prompt;
  224. char *buf;
  225. char doEcho;
  226. int  lim;    /* max # chars to read */
  227. char QuestIsSpecial;    /* Return immediately on '?' input?        */
  228. {
  229.     char c, oldEcho;
  230.     int  i;
  231.  
  232.     outFlag = IMPERVIOUS;
  233.  
  234.     if (strLen(prompt) > 0) {
  235.     doCR();
  236.     mPrintf("Enter %s\n : ", prompt, lim);
  237.     }
  238.  
  239.     oldEcho = echo;
  240.     if (!doEcho) {
  241.     echo     = NEITHER;
  242.     echoChar = 'X';
  243.     }
  244.  
  245.     i    = 0;
  246.     while (
  247.      c = iChar(),
  248.  
  249.      c      != NEWLINE
  250.      && i      <  lim
  251.      && onLine()
  252.     ) {
  253.     outFlag = OUTOK;
  254.  
  255.     /* handle delete chars: */
  256.     if (c == BACKSPACE) {
  257.         oChar(' ');
  258.         oChar(BACKSPACE);
  259.         if (i > 0) i--;
  260.         else  {
  261.         oChar(' ');
  262.         oChar(BELL);
  263.         }
  264.     } else     buf[i++] = c;
  265.  
  266.     if (i >= lim) {
  267.         oChar(BELL);
  268.         oChar(BACKSPACE); i--;
  269.     }
  270.  
  271.     /* kludge to return immediately on single '?': */
  272.     if (QuestIsSpecial && *buf == '?')   {
  273.         doCR();
  274.         break;
  275.     }
  276.     }
  277.     echo    = oldEcho;
  278.     buf[i]  = '\0';
  279. }
  280.  
  281. /************************************************************************/
  282. /*    getText() reads a message from the user             */
  283. /*    Returns TRUE if user decides to save it, else FALSE        */
  284. /************************************************************************/
  285. char getText(prompt, recipient, mode)
  286. char *prompt;
  287. char mode;
  288. char *recipient;    /* Meaningful iff thisRoom == MAILROOM */
  289. {
  290. #ifdef NEED_VISIBLE
  291.     char visible();
  292. #endif
  293.     char c, sysopAbort, *buf, beeped = FALSE;
  294.     int  i, toReturn, lim;
  295.  
  296.     if (!expert) {
  297.         tutorial("entry.blb");
  298.         mPrintf("Enter %s (end with empty line)", prompt);
  299.     }
  300.     outFlag = OUTOK;
  301.     doCR();
  302.     mPrintf("   ");
  303.     printDate();
  304.     if (loggedIn)          mPrintf("from %s", msgBuf.mbauth);
  305.     if (thisRoom == MAILROOM) mPrintf(" to %s", recipient);
  306.     if (msgBuf.mbaddr[0])     mPrintf(" (on %s)", msgBuf.mbaddr);
  307.     doCR();
  308.  
  309.     buf = msgBuf.mbtext;
  310.     if (!mode) {
  311.     buf[-1] = NEWLINE;
  312.     buf[ 0] = 0;
  313.     toReturn = TRUE;
  314.     }
  315.     else {
  316.         outFlag = OUTOK;
  317.         mFormat(buf);
  318.     outFlag = OUTOK;
  319.         doCR();
  320.         toReturn = ERROR;
  321.     }
  322.     outFlag = OUTOK;
  323.     lim     = MAXTEXT;
  324.  
  325.     lim--;
  326.     i  = strLen(buf);
  327.     sysopAbort    = FALSE;
  328.     do {
  329. #ifdef NOTFASTENOUGH
  330.     if (whichIO == MODEM)    {
  331.         fastIn(toReturn == ERROR);
  332.         if (whichIO != MODEM)   sysopAbort    = TRUE;
  333.     } else {
  334. #endif
  335.        /* this code would handle the modem as well...    */
  336.        /* fastIn() is a later addition to handle people    */
  337.        /* who like to upload fast without handshaking    */
  338.             i = strLen(buf);
  339.         while (
  340.         !(
  341.             (c=iChar()) == NEWLINE   &&
  342.             (buf[i-1] == NEWLINE || i == 0)
  343.         )
  344.         && i < lim
  345.         && onLine()
  346.         ) {
  347. #ifdef NEED_VISIBLE
  348.            if (debug) mputChar(visible(c));
  349. #endif
  350.  
  351.         if (c != BACKSPACE) {
  352.             if (c != 0) buf[i++]   = c;
  353.             if (i > MAXTEXT - 80 && !beeped) {
  354.             beeped = TRUE;
  355.             oChar(BELL);
  356.             }
  357.         }
  358.         else {
  359.              /* handle delete chars: */
  360.             oChar(' ');
  361.             oChar(BACKSPACE);
  362.             if (i > 0 && buf[i-1] != NEWLINE)    i--;
  363.             else                oChar(BELL);
  364.         }
  365.        /*   }     */
  366.  
  367.         buf[i] = 0x00;        /* null to terminate message     */
  368.  
  369.         if (i == lim)   mPrintf(" buffer overflow\n ");
  370.     }
  371.     toReturn    =    sysopAbort  ?  FALSE  :  editText(buf, lim);
  372.     } while ((toReturn == ERROR)  &&  onLine());
  373.     if (toReturn == TRUE) {        /* Filter null messages     */
  374.     toReturn = FALSE;
  375.     for (i = 0; buf[i] != 0 && toReturn == FALSE; i++)
  376.         toReturn = (buf[i] > ' ' && buf[i] < 127);
  377.     }
  378.     return  toReturn;
  379. }
  380.  
  381. /************************************************************************/
  382. /*    getYesNo() prompts for a yes/no response            */
  383. /************************************************************************/
  384. char getYesNo(prompt)
  385. char *prompt;
  386. {
  387.     int  toReturn;
  388.  
  389.     for (doCR(), toReturn = ERROR; toReturn == ERROR && onLine(); ) {
  390.     outFlag = IMPERVIOUS;
  391.     mPrintf("%s? (Y/N): ", prompt);
  392.  
  393.     switch (toUpper(iChar())) {
  394.     case 'Y': toReturn    = TRUE ;        break;
  395.     case 'N': toReturn    = FALSE;        break;
  396.     }
  397.     doCR();
  398.     }
  399.     outFlag = OUTOK;
  400.     return   toReturn;
  401. }
  402.  
  403. /************************************************************************/
  404. /*    givePrompt() prints the usual "CURRENTROOM>" prompt.        */
  405. /************************************************************************/
  406. givePrompt()
  407. {
  408.     outFlag = IMPERVIOUS;
  409.     doCR();
  410.     if (loggedIn)   printf("(%s)\n", logBuf.lbname);
  411.     mPrintf(roomBuf.rbflags.MSDOSDIR == 0 ? "%s> " : "%s] ", roomBuf.rbname);
  412.  
  413.     if (strCmp(roomBuf.rbname, roomTab[thisRoom].rtname) != SAMESTRING) {
  414.     exitValue = CRASH_EXIT;
  415.     crashout("Dependent variables mismatch!");
  416.     }
  417.     outFlag = OUTOK;
  418. }
  419.  
  420. /************************************************************************/
  421. /*    good_path() Gets a valid path from the sysop. Drive should be    */
  422. /*            set already.                    */
  423. /************************************************************************/
  424. good_path(buffer, size)
  425. char *buffer;
  426. int  size;
  427. {
  428.     char *cd, *gcdir();
  429.     char gooddir;
  430.  
  431.     cd = gcdir("");
  432.     buffer[0] = '\\';
  433.     do {
  434.     mPrintf("\n Path: \\");
  435.     getString("", buffer+1, size - 1, FALSE, ECHO, FALSE);
  436.     gooddir = ((chdir(buffer) != EOF) || buffer[1] == '?');
  437.     if (!gooddir) printf("Directory not found.\n");
  438.     } while (!gooddir);
  439.     chdir(cd);
  440.     free(cd);
  441. }
  442.  
  443. /************************************************************************/
  444. /*    indexRooms() -- build RAM index to CTDLROOM.SYS, by CITADEL, to */
  445. /*    delete empty rooms.                        */
  446. /************************************************************************/
  447. indexRooms()
  448. {
  449.     int  goodRoom, m, slot;
  450.  
  451.     for (slot = 0;  slot < MAXROOMS;  slot++) {
  452.     if (roomTab[slot].rtflags.INUSE == 1) {
  453.         goodRoom = FALSE;
  454.         if (roomTab[slot].rtlastMessage > cfg.oldest ||
  455.         roomTab[slot].rtflags.PERMROOM == 1) {
  456.         goodRoom    = TRUE;
  457.         }
  458.  
  459.         if (!goodRoom) {
  460.         getRoom(slot);
  461.         roomBuf.rbflags.INUSE     = 0;
  462.         roomBuf.rbflags.MSDOSDIR = 0;
  463.         roomBuf.rbflags.PERMROOM = 0;
  464.         roomBuf.rbflags.INUSE     = 0;
  465.         putRoom(slot);
  466.         strCat(msgBuf.mbtext, roomBuf.rbname);
  467.         strCat(msgBuf.mbtext, "> ");
  468.         noteRoom();
  469.         }
  470.     }
  471.     }
  472. }
  473.  
  474. /************************************************************************/
  475. /*    makeRoom() constructs a new room via dialogue with user.    */
  476. /************************************************************************/
  477. makeRoom()
  478. {
  479.     char *nm[NAMESIZE];
  480.     char *oldName[NAMESIZE];
  481.     int  i;
  482.  
  483.     /* update lastMessage for current room: */
  484.     logBuf.lbgen[thisRoom]    = roomBuf.rbgen << GENSHIFT;
  485.  
  486.     strCpy(oldName, roomBuf.rbname);
  487.     if ((thisRoom = findRoom()) == ERROR) {
  488.     indexRooms();    /* try and reclaim an empty room    */
  489.     if ((thisRoom = findRoom()) == ERROR) {
  490.         mPrintf(" ?no room, sorry");
  491.         /* may have reclaimed old room, so: */
  492.         if (roomExists(oldName) == ERROR)    strCpy(oldName, baseRoom);
  493.         getRoom(roomExists(oldName));
  494.         return;
  495.     }
  496.     }
  497.  
  498.     getNormStr("name for new room", nm, NAMESIZE, ECHO);
  499.     if (strLen(nm) == 0) {
  500.     if (roomExists(oldName) == ERROR)   strCpy(oldName, baseRoom);
  501.     getRoom(roomExists(oldName));
  502.     return ;
  503.     }
  504.  
  505.     if (roomExists(nm) >= 0) {
  506.     mPrintf(" A '%s' already exists.\n", nm);
  507.     /* may have reclaimed old room, so: */
  508.     if (roomExists(oldName) == ERROR)   strCpy(oldName, baseRoom);
  509.     getRoom(roomExists(oldName));
  510.     return;
  511.     }
  512.     if (!expert)   tutorial("newroom.blb");
  513.  
  514.     roomBuf.rbflags.INUSE    = TRUE;
  515.     roomBuf.rbflags.PERMROOM = FALSE;
  516.     roomBuf.rbflags.MSDOSDIR = FALSE;
  517.     if (getYesNo(" Make room public")) roomBuf.rbflags.PUBLIC = TRUE;
  518.     else                   roomBuf.rbflags.PUBLIC = FALSE;
  519.  
  520.     mPrintf("'%s', a %s room",
  521.     nm,
  522.     roomBuf.rbflags.PUBLIC == 1  ?    "public"  :  "private"
  523.     );
  524.  
  525.     if(!getYesNo("Install it")) {
  526.     /* may have reclaimed old room, so: */
  527.     if (roomExists(oldName) == ERROR)   strCpy(oldName, baseRoom);
  528.     getRoom(roomExists(oldName));
  529.     return;
  530.     }
  531.  
  532.     strCpy(roomBuf.rbname, nm);
  533.     for (i = 0;  i < MSGSPERRM;  i++) {
  534.     roomBuf.msg[i].rbmsgNo     = 0l;     /* mark all slots empty */
  535.     roomBuf.msg[i].rbmsgLoc  = 0 ;
  536.     }
  537.     roomBuf.rbgen = (roomTab[thisRoom].rtgen + 1) % MAXGEN;
  538.  
  539.     noteRoom();             /* index new room    */
  540.     putRoom(thisRoom);
  541.  
  542.     /* update logBuf: */
  543.     logBuf.lbgen[thisRoom]    = roomBuf.rbgen << GENSHIFT;
  544.     sprintf(msgBuf.mbtext, "%s> created by %s", nm, logBuf.lbname);
  545.     aideMessage(FALSE);
  546. }
  547.  
  548. /************************************************************************/
  549. /*    matchString() searches for match to given string.  Runs backward*/
  550. /*    through buffer so we get most recent error first.        */
  551. /*    Returns loc of match, else ERROR                */
  552. /************************************************************************/
  553. char *matchString(buf, pattern, bufEnd)
  554. char *buf, *pattern, *bufEnd;
  555. {
  556.     char *loc, *pc1, *pc2;
  557.     char foundIt;
  558.  
  559.     for (loc = bufEnd, foundIt = FALSE;  !foundIt && --loc >= buf;) {
  560.     for (pc1 = pattern, pc2 = loc,    foundIt = TRUE ;  *pc1 && foundIt;) {
  561.         if (! (toLower(*pc1++) == toLower(*pc2++)))   foundIt = FALSE;
  562.     }
  563.     }
  564.  
  565.     return   foundIt  ?  loc  :  ERROR;
  566. }
  567.  
  568. /************************************************************************/
  569. /*    getNormStr() gets a string and deletes leading            */
  570. /*                      & trailing blanks etc.    */
  571. /************************************************************************/
  572. getNormStr(prompt, s, size, doEcho)
  573. char *s, *prompt;
  574. char doEcho;
  575. int  size;
  576. {
  577.     char *pc;
  578.  
  579.     getString(prompt, s, size, FALSE, doEcho);
  580.     pc = s;
  581.  
  582.     /* find end of string   */
  583.     while (*pc)   {
  584.     if (*pc < ' ')     *pc = ' ';   /* zap tabs etc... */
  585.     pc++;
  586.     }
  587.  
  588.     /* no trailing spaces: */
  589.     while (pc>s  &&  isSpace(*(pc-1))) pc--;
  590.     *pc = '\0';
  591.  
  592.     /* no leading spaces: */
  593.     while (*s == ' ') {
  594.     for (pc=s;  *pc;  pc++)    *pc = *(pc+1);
  595.     }
  596.  
  597.     /* no double blanks */
  598.     for (;  *s;  s++)    {
  599.     if (*s == ' '    &&   *(s+1) == ' ')   {
  600.         for (pc=s;    *pc;  pc++)    *pc = *(pc+1);
  601.     }
  602.     }
  603. }
  604.  
  605. /************************************************************************/
  606. /*    noteRoom() -- enter room into RAM index array.            */
  607. /************************************************************************/
  608. noteRoom()
  609. {
  610.     int   i;
  611.     ulong last;
  612.  
  613.     last = 0l;
  614.     for (i = 0;  i < MSGSPERROOM;  i++)  {
  615.     if (roomBuf.msg[i].rbmsgNo > last) {
  616.         last = roomBuf.msg[i].rbmsgNo;
  617.     }
  618.     }
  619.     roomTab[thisRoom].rtlastMessage = last         ;
  620.     strCpy(roomTab[thisRoom].rtname, roomBuf.rbname) ;
  621.     roomTab[thisRoom].rtgen        = roomBuf.rbgen  ;
  622.     roomTab[thisRoom].rtflags.INUSE    = roomBuf.rbflags.INUSE;
  623.     roomTab[thisRoom].rtflags.PUBLIC   = roomBuf.rbflags.PUBLIC;
  624.     roomTab[thisRoom].rtflags.MSDOSDIR = roomBuf.rbflags.MSDOSDIR;
  625.     roomTab[thisRoom].rtflags.PERMROOM = roomBuf.rbflags.PERMROOM;
  626.     roomTab[thisRoom].rtflags.SKIP     = roomBuf.rbflags.SKIP;
  627. }
  628.  
  629. /************************************************************************/
  630. /*    renameRoom() is sysop special fn                */
  631. /*    Returns:    TRUE on success else FALSE            */
  632. /************************************************************************/
  633. renameRoom()
  634. {
  635.     char nm[NAMESIZE];
  636.     char c, goodOne, wasDirectory;
  637.     int  r;
  638.  
  639.     if (                /* clearer than "thisRoom <= AIDEROOM"*/
  640.     thisRoom == LOBBY
  641.     ||
  642.     thisRoom == MAILROOM
  643.     ||
  644.     thisRoom == AIDEROOM
  645.     ) {
  646.     mPrintf("? -- may not edit this room.\n ");
  647.     return FALSE;
  648.     }
  649.  
  650.     if (!getYesNo("confirm"))    return FALSE;
  651.  
  652.     if (getYesNo("Change name"))   {
  653.     getNormStr("new room name", nm, NAMESIZE, ECHO);
  654.     r = roomExists(nm);
  655.     if (r >= 0  &&    r != thisRoom) {
  656.          mPrintf("A %s exists already!\n", nm);
  657.     } else {
  658.         strCpy(roomBuf.rbname, nm);   /* also in room itself  */
  659.     }
  660.     }
  661.     mPrintf("%s, ", roomBuf.rbflags.PUBLIC == 1 ? "public" : "private");
  662.     mPrintf(
  663.     "%s, ",
  664.     (
  665.         (roomBuf.rbflags.PERMROOM == 1)
  666.         ?
  667.         " permanent"
  668.         :
  669.         " temporary"
  670.     )
  671.     );
  672.     wasDirectory = roomBuf.rbflags.MSDOSDIR;
  673.     mPrintf("%sdirectory room\n ", wasDirectory  ?  "" : "non");
  674.  
  675.     roomBuf.rbflags.INUSE = TRUE;
  676.  
  677.     if (getYesNo("Public room"))    {
  678.     roomBuf.rbflags.PUBLIC = TRUE;
  679.     } else {
  680.     roomBuf.rbflags.PUBLIC = FALSE;     /* JUST in case */
  681.     if (getYesNo("Cause non-aide users to forget room"))
  682.         roomBuf.rbgen    = (roomBuf.rbgen +1) % MAXGEN;
  683.     }
  684.  
  685.     if (!onConsole)   roomBuf.rbflags.MSDOSDIR = wasDirectory;
  686.     else if (getYesNo("Directory room")) {
  687.     if (roomBuf.rbflags.MSDOSDIR == TRUE)
  688.         printf("Currently drive %c, directory %s\n",
  689.             'A'+roomBuf.rbdisk,
  690. (strLen(roomBuf.rbdirname) == 0 ? "is current directory" : roomBuf.rbdirname));
  691.  
  692.     roomBuf.rbflags.MSDOSDIR = TRUE;
  693.  
  694.     for (goodOne = FALSE;  !goodOne;  )   {
  695.         getString("disk", nm, NAMESIZE, FALSE, ECHO);
  696.         c        = toUpper(nm[0]);
  697.         if (c>='A'    && c<='P') {
  698.         roomBuf.rbdisk        = c - 'A';
  699.         goodOne         = TRUE;
  700.         } else printf("?");
  701.     }
  702.     setSpace(roomBuf.rbdisk, "");
  703.  
  704.     for (goodOne = FALSE;  !goodOne;  )   {
  705.         getString("directory (empty entry means use current directory)",
  706.                                nm, 9, FALSE, ECHO);
  707.         if (index(nm, ' ') != NULL)
  708.         printf("No spaces in directory names!");
  709.         else if (index(nm, '\\') != NULL)
  710.         printf("No '\\'s in directory names!");
  711.         else if (strLen(nm) == 0) {
  712.         goodOne = TRUE;
  713.         strCpy(roomBuf.rbdirname, nm);
  714.         }
  715.         else if (chdir(nm) != EOF) {
  716.         printf("%s exists. ", nm);
  717.         goodOne = getYesNo("Use it");
  718.         chdir("..");
  719.         if (goodOne)
  720.             strCpy(roomBuf.rbdirname, nm);
  721.         }
  722.         else {
  723.         printf("%s does not exist. ", nm);
  724.         goodOne = getYesNo("Create");
  725.         if (goodOne) {
  726.             if (mkdir(nm) == EOF) {
  727.             printf("?ERROR CREATING!");
  728.             roomBuf.rbflags.MSDOSDIR = FALSE;
  729.             }
  730.             else strCpy(roomBuf.rbdirname, nm);
  731.         }
  732.         }
  733.     }
  734.     setSpace(cfg.homeDisk, "");
  735.     }
  736.     else
  737.     roomBuf.rbflags.MSDOSDIR = FALSE;
  738.  
  739.     if (roomBuf.rbflags.MSDOSDIR == TRUE || getYesNo("permanent")) {
  740.     roomBuf.rbflags.PERMROOM = TRUE;
  741.     }
  742.     else
  743.     roomBuf.rbflags.PERMROOM = FALSE;
  744.  
  745.     noteRoom();
  746.     putRoom(thisRoom);
  747.  
  748.     return TRUE;
  749. }
  750.  
  751. /************************************************************************/
  752. /*    replaceString() corrects typos in message entry         */
  753. /************************************************************************/
  754. replaceString(buf, lim)
  755. char *buf;
  756. int  lim;
  757. {
  758.     char oldString[2*SECTSIZE];
  759.     char newString[2*SECTSIZE];
  760.     char *loc, *textEnd;
  761.     char *pc;
  762.     int  incr, length;
  763.  
  764.                           /* find terminal null */
  765.     for (textEnd = buf, length = 0;  *textEnd;    length++, textEnd++);
  766.  
  767.     getString("string",      oldString, (2*SECTSIZE), FALSE, ECHO);
  768.     if ((loc=matchString(buf, oldString, textEnd)) == ERROR) {
  769.     mPrintf("?not found.\n ");
  770.     return;
  771.     }
  772.  
  773.     getString("replacement", newString, (2*SECTSIZE), FALSE, ECHO);
  774.     if ( (strLen(newString)-strLen(oldString))    >=  lim - length) {
  775.     mPrintf("?Overflow!\n ");
  776.     return;
  777.     }
  778.  
  779.     /* delete old string: */
  780.     for (pc=loc, incr=strLen(oldString);  *pc=*(pc+incr);  pc++);
  781.     textEnd -= incr;
  782.  
  783.     /* make room for new string: */
  784.     for (pc=textEnd, incr=strLen(newString);  pc>=loc;    pc--) {
  785.     *(pc+incr) = *pc;
  786.     }
  787.  
  788.     /* insert new string: */
  789.     for (pc=newString;    *pc;  *loc++ = *pc++);
  790. }
  791.  
  792. /************************************************************************/
  793. /*    strTran() Transfers a string from loc to dest, then zaps loc    */
  794. /************************************************************************/
  795. strTran(dest, loc)
  796. char *dest, *loc;
  797. {
  798.     strCpy(dest, loc);
  799.     loc[0] = 0;
  800. }
  801.